大綱
附加事件處理器
在運作的過程中,React 會協助我們處理在 JavaScript 中看到的同樣事件:點擊事件的 MouseEvents
,又或表單元素改變時的 Chang 事件,等等一些動作。這個時候事件的名稱和 JavaScript 中又會是相同的,並且觸發的條件也是相同的。這時候所謂的附加事件處理器的 React 語法就會和 HTML 語法十分類似。
事件與狀態
現在我們假設的情境是根據使用者輸入而做出改變,就好比問卷編輯器,它允許使用者從任何一個題目類型的選單中把問卷題目拖曳進來。
首先呢,我們從 render 函式開始,它註冊了一些基於 HTML5 的 Drag and Drop API 的事件處理器。
基於狀態的渲染:
在這裡,其中有一件事件處理器需要做的事情是擴充已經添加的題目清單。要做到這一點,我們會需要使用每一個 React 元件都有的內部狀態物件。它預設為空值 (null),但是可以透過元件的 getInitialState()
方法來初始化為可以使用的東西,像這樣:
getInitialState: function() {
return {
dropZoneEntered: false,
title: ' ', introduction: ' ',
questions: []
};
}
這為我們的狀態建立了一條非常有意義的基線:空白的標題、空白的介紹、空白的題目清單、以及把 dropZoneEntered
的值設定為 false -- 以便指示使用者當前並未再拖放區放置任何東西。
更新狀態:
這裡要說明的是,由於在更新元件的內部狀態時會導致元件重新渲染,所以接下來我們的下一步要做的便是更新拖曳處理方法中的狀態。這個時候 render 便會再次執行,並且從 this.state 中讀取當前的值來顯示標題、介紹和題目。最後,使用者就會看到一切正確地更新了。
然後,我們有兩種方法可以更新元件的狀態:元件的 setState
方法和 replaceState
方法。replaceState
會用一個全新的狀態物件將舊的整個覆蓋掉,如果我們採用是不可變化的資料結構來保存我們元件的狀態,哪這個方法就會粉好用,不然的話,通常這也不會是我們要的。在這種情況下,更多的時候我們就會選擇使用 setState
,哪這樣一來會單純地把我們提供的物件合併到原本的狀態物件。
以下,舉一個例子,我們來假設存在以下的狀態:
getInitialState: function() {
return {
dropZoneEntered: false,
title: 'Fantastic Survey',
introduction: 'This survey is fantastic!',
question: [ ]
};
}
在這種情況下,呼叫 this.setState({ title: ''Fantastic Survey 2.0'})
,這只會影響到 this.state.title
的值,其餘的 this.state.dropZoneEntered
、this.state.introduction
以及 this.state.question
是不會受到影響的。
另外,要特別說明的一點是永遠不要透過呼叫 setState
又或是 replaceState
以外的方法來改變狀態中的物件。像 this.state.saveInProgress = true
這樣的做法是很不好的,因為這會通知 React 進行重新渲染,可能會導致在下次呼叫 setState
時產生預期至外的結果,這會是不樂見的情況。
事件物件
在 React 中,我們擁有很多的處理器方法,對我來說只要能執行就能達到我們要的目的,但是,在某些時候我們會需要更多的關於使用者輸入的資訊來做處理及判斷。
React 的事件處理器函式總是傳遞事件物件,就像純 JavaScript 的事件監聽器一樣。舉一個例子,handleComplete 方法只接受一個事件物件,這個物件透過 event.target.value
從 textarea 中取得當前的值。哪...在事件處理器中我們使用了 event.target.value
是從表單輸入取得當前值的常見做法,特別是在 onChange 處理器當中。
最後,React 並不是直接把瀏覽器的 Event 物件傳給處理器,而是把原生的事件封裝到一個 SyntheticEvent
實作當中。SyntheticEvent
跟瀏覽器原生事件的外表和功能都是一樣的,除了增加了一些使跨瀏覽器運作更加平順的解決方案。我們也可以像使用一般事件一樣使用 SyntheticEvent
,但是呢,如果今天是我們要用到瀏覽器的原生事件,我們就可以透過 SyntheticEvent
的 nativeEvent
欄位取得。